package cn.itsource.basic.service.Impl;

import cn.itsource.basic.dto.UserSmsCodeDto;
import cn.itsource.basic.exception.BusinessException;
import cn.itsource.basic.service.IVerifyCodeService;
import cn.itsource.basic.util.AjaxResult;
import cn.itsource.basic.util.SmsUtil;
import cn.itsource.basic.util.StrUtils;
import cn.itsource.basic.util.VerifyCodeUtils;
import cn.itsource.org.domain.User;
import cn.itsource.org.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public AjaxResult genterateImgCode(String uuid) {
        String imgContext = StrUtils.getRandomString(1);
        String finalImg = VerifyCodeUtils.VerifyCode(115, 45, imgContext);
        //System.out.println(finalImg);
        //保存到redis,后面发短信要用来校验
        redisTemplate.opsForValue().set(uuid,imgContext,3, TimeUnit.MINUTES);
        return AjaxResult.me().setResultObj(finalImg);
    }

    @Override
    public void sendCode(UserSmsCodeDto userSmsCodeDto) {
//        1. 参数校验
//        2. 校验用户是否注册过
        User user = userMapper.loadByPhone(userSmsCodeDto.getPhone());
        if (user != null){
            throw new BusinessException("用户已存在");
        }
//        3. 校验图形验证码
        Object imageCodeValue = redisTemplate.opsForValue().get(userSmsCodeDto.getImageCodeKey());

//               1. redis取不到(过期/对比不通过)
//                  1. 抛自定义业务异常
        if (imageCodeValue == null ){
            throw new BusinessException("图片验证码错误,请重试!");
        }
        String imageCodeValueStr = imageCodeValue.toString();
//              2. 对比不通过
//                   1. 抛自定义业务异常
        if (!imageCodeValueStr.equalsIgnoreCase(userSmsCodeDto.getImageCodeValue())){
            throw new BusinessException("图片验证码错误,请重试!");
        }
        
//        4. 先拼接短信存redis的key(手机号+业务键)去redis中查询
        String smsKey = userSmsCodeDto.getPhone() + ":register";
        Object smsValueInRedis = redisTemplate.opsForValue().get(smsKey);

        String code = null;

//        1. 查到（没过期）
        if (smsValueInRedis != null){
//            1. 判断是否过了重发时间(距离上次发送是否大于1分钟--拼接时间戳来判断)
//            1. 在一分钟之内(不允许发)
            Long oldTime = Long.valueOf(smsValueInRedis.toString().split(":")[1]);
            code = smsValueInRedis.toString().split(":")[0];
            if (System.currentTimeMillis() - oldTime < 60000){
                throw new BusinessException("请一分钟后再试!");
            }else{ //查不到/第一次发
//                2. 已经超过一分钟(拿本次查到的发短信，并且更新redis的短信验证码过期时间)
                code = StrUtils.getRandomString(1);
            }
        }
//        2. 存redis(key:手机号+业务键，VALUE：验证码+时间戳),设置过期时间3min
        code = StrUtils.getRandomString(1);
        redisTemplate.opsForValue().set(smsKey,code+":"+System.currentTimeMillis(),1,TimeUnit.MINUTES);
//              3. 通过三方短信接口发送短信---没钱
        log.info("验证码为:{}",code);
    }
}
